#include "gd32f4xx.h"
#include "sys_type.h"
#include "bsp_timer.h"
#include "bsp_iic.h"



void vIIC_Init(void)
{
    /* enable GPIOB clock */
    rcu_periph_clock_enable(RCU_GPIOB);

    /* connect I2C_SCL_PIN to I2C_SCL */
    gpio_af_set(GPIOB, GPIO_AF_4, GPIO_PIN_6);
    /* connect I2C_SDA_PIN to I2C_SDA */
    gpio_af_set(GPIOB, GPIO_AF_4, GPIO_PIN_7);
    /* configure GPIO pins of I2C */
    gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_6);
    gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_6);
    gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_7);
    gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_7);

	i2c_disable(I2C0);
    /* enable I2C clock */
    rcu_periph_clock_enable(RCU_I2C0);
    /* configure I2C clock */
    i2c_clock_config(I2C0, 100000, I2C_DTCY_2);
    /* configure I2C address */
    i2c_mode_addr_config(I2C0, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0x49);
    /* enable I2CX */
    i2c_enable(I2C0);
    /* enable acknowledge */
    i2c_ack_config(I2C0, I2C_ACK_ENABLE);

    
	//i2c_stop_on_bus(I2C0);
	//while (I2C_CTL0(I2C0) & I2C_CTL0_STOP);
}


IIC_STATUS I2C_Mem_Write(uint32_t I2Cx,u8 device_addr,u8* pBuffer, u8 WriteAddr, u16 NumByteToWrite)
{
	uint32_t tickstart = HAL_GetTick();
	uint32_t I2CTimeout = 1000;
	
    while (i2c_flag_get(I2Cx, I2C_FLAG_I2CBSY))
    {
		vBSP_WDG_Refresh();
		if ((HAL_GetTick() - tickstart) >=  I2CTimeout)
		{
			return IIC_TIMEOUT;
		}
    }
    /** Send START condition */
    i2c_start_on_bus(I2Cx);
    /** Test on EV5 and clear it */
    while (!i2c_flag_get(I2Cx, I2C_FLAG_SBSEND))
    {
		vBSP_WDG_Refresh();
		if ((HAL_GetTick() - tickstart) >=  I2CTimeout)
		{
			return IIC_TIMEOUT;
		}
    }
    /** Send EEPROM address for write */
    i2c_master_addressing(I2Cx, device_addr, I2C_TRANSMITTER);
    /** Test on EV6 and clear it */
    while (!i2c_flag_get(I2Cx, I2C_FLAG_ADDSEND))
    {
		vBSP_WDG_Refresh();
		if ((HAL_GetTick() - tickstart) >=  I2CTimeout)
		{
			return IIC_TIMEOUT;
		}
    }
	i2c_flag_clear(I2Cx, I2C_FLAG_ADDSEND);
	/* wait until the transmit data buffer is empty */
    while (!i2c_flag_get(I2Cx, I2C_FLAG_TBE))
    {
		vBSP_WDG_Refresh();
		if ((HAL_GetTick() - tickstart) >=  I2CTimeout)
		{
			return IIC_TIMEOUT;
		}
    }
    /** Send the EEPROM's internal address to write to */
    i2c_data_transmit(I2Cx, WriteAddr);
    /** Test on EV8 and clear it */
    while (!i2c_flag_get(I2Cx, I2C_FLAG_BTC))
    {
		vBSP_WDG_Refresh();
		if ((HAL_GetTick() - tickstart) >=  I2CTimeout)
		{
			return IIC_TIMEOUT;
		}
    }
    /** While there is data to be written */
    while (NumByteToWrite--)
    {
        /** Send the current byte */
        i2c_data_transmit(I2Cx, *pBuffer);
        /** Point to the next byte to be written */
        pBuffer++;
        /** Test on EV8 and clear it */
        while (!i2c_flag_get(I2Cx, I2C_FLAG_BTC))
        {
			vBSP_WDG_Refresh();
			if ((HAL_GetTick() - tickstart) >=	I2CTimeout)
			{
				return IIC_TIMEOUT;
			}
        }
    }
    /** Send STOP condition */
    i2c_stop_on_bus(I2Cx);

	while (I2C_CTL0(I2Cx) & I2C_CTL0_STOP)
	{
		vBSP_WDG_Refresh();
		if ((HAL_GetTick() - tickstart) >=	I2CTimeout)
		{
			return IIC_TIMEOUT;
		}
	}
	return IIC_OK;
}

#if 0
IIC_STATUS I2C_Mem_Read(uint32_t I2Cx,u8 device_addr,u8* pBuffer, u8 readAddr, u16 NumByteToRead)
{
	uint32_t tickstart = HAL_GetTick();
	uint32_t I2CTimeout = 1000;

    /* enable acknowledge */
    i2c_ack_config(I2Cx, I2C_ACK_ENABLE);
	
    while (i2c_flag_get(I2Cx, I2C_FLAG_I2CBSY))
    {
		vBSP_WDG_Refresh();
		if ((HAL_GetTick() - tickstart) >=I2CTimeout)
		{
			return IIC_TIMEOUT;
		}
    }
	 /* whether to send ACK or not for the next byte */
	if(2 == NumByteToRead) 
	{
		i2c_ackpos_config(I2Cx, I2C_ACKPOS_NEXT);
	}

    /** Send START condition */
    i2c_start_on_bus(I2Cx);
    /** Test on EV5 and clear it */
    while (!i2c_flag_get(I2Cx, I2C_FLAG_SBSEND))
    {
		vBSP_WDG_Refresh();
		if ((HAL_GetTick() - tickstart) >=	I2CTimeout)
		{
			return IIC_TIMEOUT;
		}
    }
    /** Send EEPROM address for write */
    i2c_master_addressing(I2Cx, device_addr, I2C_TRANSMITTER);
    /** Test on EV6 and clear it */
    while (!i2c_flag_get(I2Cx, I2C_FLAG_ADDSEND))
    {
		vBSP_WDG_Refresh();
		if ((HAL_GetTick() - tickstart) >=	I2CTimeout)
		{
			return IIC_TIMEOUT;
		}
    }
	i2c_flag_clear(I2Cx, I2C_FLAG_ADDSEND);
	 /* wait until the transmit data buffer is empty */
    while (!i2c_flag_get(I2Cx, I2C_FLAG_TBE))
    {
		vBSP_WDG_Refresh();
		if ((HAL_GetTick() - tickstart) >=  I2CTimeout)
		{
			return IIC_TIMEOUT;
		}
    }
    /** Send the EEPROM's internal address to write to */
    i2c_data_transmit(I2Cx, readAddr);
    /** Test on EV8 and clear it */
    while (!i2c_flag_get(I2Cx, I2C_FLAG_BTC))
    {
		vBSP_WDG_Refresh();
		if ((HAL_GetTick() - tickstart) >=	I2CTimeout)
		{
			return IIC_TIMEOUT;
		}
    }

    
    /** Send STRAT condition a second time */
    i2c_start_on_bus(I2Cx);
    /** Test on EV5 and clear it */
    while (!i2c_flag_get(I2Cx, I2C_FLAG_SBSEND))
    {
		vBSP_WDG_Refresh();
		if ((HAL_GetTick() - tickstart) >=	I2CTimeout)
		{
			return IIC_TIMEOUT;
		}
    }
	
    /** Send EEPROM address for read */
    i2c_master_addressing(I2Cx, device_addr, I2C_RECEIVER);
	if (NumByteToRead < 3)
	{
		//可以移到下面去
		 i2c_ack_config(I2Cx, I2C_ACK_DISABLE);
	}

    /* Test on EV6 and clear it */
    while (!i2c_flag_get(I2Cx, I2C_FLAG_ADDSEND))    //EV6
    {
		vBSP_WDG_Refresh();
		if ((HAL_GetTick() - tickstart) >=	I2CTimeout)
		{
			return IIC_TIMEOUT;
		}
    }
	i2c_flag_clear(I2Cx, I2C_FLAG_ADDSEND);
	
    /** While there is data to be read */
    if (NumByteToRead == 1)
    {
		/* send a stop condition to I2C bus */
		i2c_stop_on_bus(I2Cx);
    }
//    else if (NumByteToRead == 2)
//    {
//        I2Cx->CTRL1 |= 0x0800; /// set POSEN
//        (void)(I2Cx->STS1);
//        (void)(I2Cx->STS2);
//        I2C_ConfigAck(I2Cx, DISABLE);
//    }
//    else
//    {
//        I2C_ConfigAck(I2Cx, ENABLE);
//        (void)(I2Cx->STS1);
//        (void)(I2Cx->STS2);
//    }
    while (NumByteToRead)
    {
        if (NumByteToRead == 3)
        {
			/* wait until BTC bit is set */
            while (!i2c_flag_get(I2Cx, I2C_FLAG_BTC))
            {
				vBSP_WDG_Refresh();
				if ((HAL_GetTick() - tickstart) >=	I2CTimeout)
				{
					return IIC_TIMEOUT;
				}
            }
			/* disable acknowledge */
			i2c_ack_config(I2Cx, I2C_ACK_DISABLE);
		}
        else if (NumByteToRead == 2)
        {
			/* wait until BTC bit is set */
            while (!i2c_flag_get(I2Cx, I2C_FLAG_BTC))
            {
				vBSP_WDG_Refresh();
				if ((HAL_GetTick() - tickstart) >=	I2CTimeout)
				{
					return IIC_TIMEOUT;
				}
            }
			/* send a stop condition to I2C bus */
			i2c_stop_on_bus(I2Cx);
		}

		while (!i2c_flag_get(I2Cx, I2C_FLAG_RBNE))
		{
			vBSP_WDG_Refresh();
			if ((HAL_GetTick() - tickstart) >=	I2CTimeout)
			{
				return IIC_TIMEOUT;
			}
		}
		*pBuffer = i2c_data_receive(I2Cx);
		/** Point to the next location where the byte read will be saved */
		pBuffer++;
		/** Decrement the read bytes counter */
		NumByteToRead--;
		
		
//        if (NumByteToRead <= 3)
//        {
//            /** One byte */
//            if (NumByteToRead == 1)
//            {
//                /** Wait until RXNE flag is set */
//                while (!I2C_GetFlag(I2Cx, I2C_FLAG_RXDATNE))
//                {
//					vBSP_WDG_Refresh();
//					if ((HAL_GetTick() - tickstart) >=	I2CTimeout)
//					{
//						return IIC_TIMEOUT;
//					}
//                }
//                /** Read data from DAT */
//                /** Read a byte from the EEPROM */
//                *pBuffer = I2C_RecvData(I2Cx);
//                /** Point to the next location where the byte read will be saved */
//                pBuffer++;
//                /** Decrement the read bytes counter */
//                NumByteToRead--;
//            }
//            /** Two bytes */
//            else if (NumByteToRead == 2)
//            {
//                /** Wait until BTF flag is set */
//                while (!I2C_GetFlag(I2Cx, I2C_FLAG_BYTEF))
//                {
//					vBSP_WDG_Refresh();
//					if ((HAL_GetTick() - tickstart) >=	I2CTimeout)
//					{
//						return IIC_TIMEOUT;
//					}
//                }
//                /** Send STOP Condition */
//                I2C_GenerateStop(I2Cx, ENABLE);

//                /** Read data from DAT */
//                *pBuffer = I2C_RecvData(I2Cx);
//                /** Point to the next location where the byte read will be saved */
//                pBuffer++;
//                /** Decrement the read bytes counter */
//                NumByteToRead--;
//                /** Read data from DAT */
//                *pBuffer = I2C_RecvData(I2Cx);
//                /** Point to the next location where the byte read will be saved */
//                pBuffer++;
//                /** Decrement the read bytes counter */
//                NumByteToRead--;
//            }
//            /** 3 Last bytes */
//            else
//            {
//                while (!I2C_GetFlag(I2Cx, I2C_FLAG_BYTEF))
//                {
//					vBSP_WDG_Refresh();
//					if ((HAL_GetTick() - tickstart) >=	I2CTimeout)
//					{
//						return IIC_TIMEOUT;
//					}
//                }
//                /** Disable Acknowledgement */
//                I2C_ConfigAck(I2Cx, DISABLE);
//                /** Read data from DAT */
//                *pBuffer = I2C_RecvData(I2Cx);
//                /** Point to the next location where the byte read will be saved */
//                pBuffer++;
//                /** Decrement the read bytes counter */
//                NumByteToRead--;

//                /** Wait until BTF flag is set */
//                while (!I2C_GetFlag(I2Cx, I2C_FLAG_BYTEF))
//                {
//					vBSP_WDG_Refresh();
//					if ((HAL_GetTick() - tickstart) >=	I2CTimeout)
//					{
//						return IIC_TIMEOUT;
//					}
//                }
//                /** Send STOP Condition */
//                I2C_GenerateStop(I2Cx, ENABLE);

//                /** Read data from DAT */
//                *pBuffer = I2C_RecvData(I2Cx);
//                /** Point to the next location where the byte read will be saved */
//                pBuffer++;
//                /** Decrement the read bytes counter */
//                NumByteToRead--;

//                /** Read data from DAT */
//                *pBuffer = I2C_RecvData(I2Cx);
//                /** Point to the next location where the byte read will be saved */
//                pBuffer++;
//                /** Decrement the read bytes counter */
//                NumByteToRead--;
//            }
//        }
//        else
//        {
//            /** Test on EV7 and clear it */
//            while (!I2C_CheckEvent(I2Cx, I2C_EVT_MASTER_DATA_RECVD_FLAG))
//            {
//				vBSP_WDG_Refresh();
//				if ((HAL_GetTick() - tickstart) >=	I2CTimeout)
//				{
//					return IIC_TIMEOUT;
//				}
//            }
//            /** Read a byte from the EEPROM */
//            *pBuffer = I2C_RecvData(I2Cx);
//            /** Point to the next location where the byte read will be saved */
//            pBuffer++;
//            /** Decrement the read bytes counter */
//            NumByteToRead--;
//            if (I2C_GetFlag(I2Cx, I2C_FLAG_BYTEF))
//            {
//                /** Read a byte from the EEPROM */
//                *pBuffer = I2C_RecvData(I2Cx);
//                /** Point to the next location where the byte read will be saved */
//                pBuffer++;
//                /** Decrement the read bytes counter */
//                NumByteToRead--;
//            }
//        }
    }
	return IIC_OK;
}

#else


IIC_STATUS I2C_Mem_Read(uint32_t I2Cx,u8 device_addr,u8* pBuffer, u8 readAddr, u16 NumByteToRead)
{
	uint32_t tickstart = HAL_GetTick();
	uint32_t I2CTimeout = 1000;

    /* enable acknowledge */
    i2c_ack_config(I2Cx, I2C_ACK_ENABLE);
	
    while(i2c_flag_get(I2Cx, I2C_FLAG_I2CBSY))
    {
		vBSP_WDG_Refresh();
		if ((HAL_GetTick() - tickstart) >=I2CTimeout)
		{
			return IIC_TIMEOUT;
		}
    }

    /** Send START condition */
    i2c_start_on_bus(I2Cx);
    /** Test on EV5 and clear it */
    while (!i2c_flag_get(I2Cx, I2C_FLAG_SBSEND))
    {
		vBSP_WDG_Refresh();
		if ((HAL_GetTick() - tickstart) >=	I2CTimeout)
		{
			return IIC_TIMEOUT;
		}
    }
    /** Send EEPROM address for write */
    i2c_master_addressing(I2Cx, device_addr, I2C_TRANSMITTER);
    /** Test on EV6 and clear it */
    while (!i2c_flag_get(I2Cx, I2C_FLAG_ADDSEND))
    {
		vBSP_WDG_Refresh();
		if ((HAL_GetTick() - tickstart) >=	I2CTimeout)
		{
			return IIC_TIMEOUT;
		}
    }
	i2c_flag_clear(I2Cx, I2C_FLAG_ADDSEND);
	 /* wait until the transmit data buffer is empty */
    while (!i2c_flag_get(I2Cx, I2C_FLAG_TBE))
    {
		vBSP_WDG_Refresh();
		if ((HAL_GetTick() - tickstart) >=  I2CTimeout)
		{
			return IIC_TIMEOUT;
		}
    }
    /** Send the EEPROM's internal address to write to */
    i2c_data_transmit(I2Cx, readAddr);
    /** Test on EV8 and clear it */
    while (!i2c_flag_get(I2Cx, I2C_FLAG_BTC))
    {
		vBSP_WDG_Refresh();
		if ((HAL_GetTick() - tickstart) >=	I2CTimeout)
		{
			return IIC_TIMEOUT;
		}
    }

    
    /** Send STRAT condition a second time */
    i2c_start_on_bus(I2Cx);
    /** Test on EV5 and clear it */
    while (!i2c_flag_get(I2Cx, I2C_FLAG_SBSEND))
    {
		vBSP_WDG_Refresh();
		if ((HAL_GetTick() - tickstart) >=	I2CTimeout)
		{
			return IIC_TIMEOUT;
		}
    }
	
    /** Send EEPROM address for read */
    i2c_master_addressing(I2Cx, device_addr, I2C_RECEIVER);

    /* Test on EV6 and clear it */
    while (!i2c_flag_get(I2Cx, I2C_FLAG_ADDSEND))    //EV6
    {
		vBSP_WDG_Refresh();
		if ((HAL_GetTick() - tickstart) >=	I2CTimeout)
		{
			return IIC_TIMEOUT;
		}
    }
	i2c_flag_clear(I2Cx, I2C_FLAG_ADDSEND);
	
    /** While there is data to be read */
    if (NumByteToRead == 1)
    {
		/* send a stop condition to I2C bus */
		i2c_ack_config(I2Cx, I2C_ACK_DISABLE);
		i2c_stop_on_bus(I2Cx);
    }
	 /* whether to send ACK or not for the next byte */
	else if(2 == NumByteToRead) 
	{
		i2c_ack_config(I2Cx, I2C_ACK_DISABLE);
		i2c_ackpos_config(I2Cx, I2C_ACKPOS_NEXT);
	}
	
    while (NumByteToRead)
    {
        if (NumByteToRead == 2)
        {
			/* wait until BTC bit is set */
            while (!i2c_flag_get(I2Cx, I2C_FLAG_BTC))
            {
				vBSP_WDG_Refresh();
				if ((HAL_GetTick() - tickstart) >=	I2CTimeout)
				{
					return IIC_TIMEOUT;
				}
            }
			/* send a stop condition to I2C bus */
			i2c_stop_on_bus(I2Cx);
		}

		while (!i2c_flag_get(I2Cx, I2C_FLAG_RBNE))
		{
			vBSP_WDG_Refresh();
			if ((HAL_GetTick() - tickstart) >=	I2CTimeout)
			{
				return IIC_TIMEOUT;
			}
		}
		*pBuffer = i2c_data_receive(I2Cx);
		/** Point to the next location where the byte read will be saved */
		pBuffer++;
		/** Decrement the read bytes counter */
		NumByteToRead--;

    }

	/* i2c master sends STOP signal successfully */
	while (I2C_CTL0(I2Cx) & I2C_CTL0_STOP)
	{
		vBSP_WDG_Refresh();
		if ((HAL_GetTick() - tickstart) >=	I2CTimeout)
		{
			return IIC_TIMEOUT;
		}
	}
	
	return IIC_OK;
}
#endif
